﻿using System;
using System.Reflection;
using LinFu.IoC;
using LinFu.IoC.Configuration;

using LinFu.IoC.Interfaces;
using CoreEx.Services;

namespace CoreEx.DynamicInvoker
{
    /// <summary>
    /// Adds fast dynamic invoke capabilites to the .Net Framework
    /// </summary>    
    public static class DynamicExtensions
    {       
        private static readonly IDynamicInvoker _dynamicInvoker;
        private static readonly IMemberInvoker _memberInvoker;
                
        /// <summary>
        /// Creates a new instance of the <see cref="DynamicExtensions"/> class.
        /// </summary>
        static DynamicExtensions()  
        {            
            _dynamicInvoker = ServiceLocator.Container.GetService<IDynamicInvoker>();
            _memberInvoker = ServiceLocator.Container.GetService<IMemberInvoker>();
        }

        


        public static object DynamicInvoke(this Type type, string memberName, params object[] arguments)
        {
            return _dynamicInvoker.Invoke(type, memberName, arguments);
        }

        public static object DynamicInvoke(this Type type, object target, string memberName, params object[] arguments)
        {
            return _dynamicInvoker.Invoke(target, memberName, arguments);
        }

        /// <summary>
        /// Invokes the instance <see cref="MethodBase"/> member using the given arguments.
        /// </summary>
        /// <param name="memberInfo">The <see cref="MethodBase"/> member to invoke.</param>
        /// <param name="target">The object on witch to invoke the member.</param>
        /// <param name="arguments">An array containing the arguments used to invoke the member.</param>
        /// <returns>An <see cref="object"/> representing the return value of the invoked member.</returns>
        public static object DynamicInvoke(this MethodBase memberInfo, object target, params object[] arguments)
        {            
            return _memberInvoker.Invoke(target, memberInfo, arguments);            
        }

        /// <summary>
        /// Invokes the static/shared <see cref="MethodBase"/> member using the given arguments.
        /// </summary>
        /// <param name="memberInfo">The <see cref="MethodBase"/> member to invoke.</param>        
        /// <param name="arguments">An array containing the arguments used to invoke the member.</param>
        /// <returns>An <see cref="object"/> representing the return value of the invoked member.</returns>
        public static object DynamicInvoke(this MethodBase memberInfo, params object[] arguments)
        {
            return _memberInvoker.Invoke(memberInfo, arguments);            
        }


        /// <summary>
        /// Invokes the instance <see cref="propertyInfo"/> member using the given arguments.
        /// </summary>
        /// <param name="propertyInfo">The <see cref="propertyInfo"/> member to invoke.</param>
        /// <param name="target">The object on witch to invoke the member.</param>
        /// <param name="arguments">An array containing the arguments used to invoke the member.</param>
        /// <returns>An <see cref="object"/> representing the return value of the invoked member.</returns>
        public static object DynamicInvoke(this PropertyInfo propertyInfo, object target, params object[] arguments)
        {
            return _memberInvoker.Invoke(target, propertyInfo, arguments);
        }

        /// <summary>
        /// Invokes the static/shared property using the given arguments.
        /// </summary>
        /// <param name="propertyInfo">The property to invoke.</param>        
        /// <param name="arguments">An array containing the arguments used to invoke the member.</param>
        /// <returns>An <see cref="object"/> representing the return value of the invoked member.</returns>
        public static object DynamicInvoke(this PropertyInfo propertyInfo, params object[] arguments)
        {
            return _memberInvoker.Invoke(propertyInfo, arguments);
        }


        /// <summary>
        /// Invokes the <see cref="ConstructorInfo"/> member using the given arguments.
        /// </summary>
        /// <param name="constructorInfo">The constructor to invoke.</param>
        /// <param name="arguments">An array containing the arguments used to invoke the member.</param>
        /// <returns>An <see cref="object"/> representing the return value of the invoked member.</returns>
        public static object DynamicInvoke(this ConstructorInfo constructorInfo, params object [] arguments)
        {
            return _memberInvoker.Invoke(constructorInfo, arguments);
        }



        public static object DynamicInvoke(this FieldInfo fieldInfo, object target, params object[] arguments)
        {
            return _memberInvoker.Invoke(target, fieldInfo, arguments);
        }


        public static MethodHandler CreateDelegate(this MethodBase memberInfo, object target, params object[] arguments)
        {
            return null;
        }

    }
}
